-- Sequence
-- create by zouyb
-- 战斗的流程控制(界面表现)

require("game/ui/base/ActionState");
require("game/ui/sequence/action/ActionBase");
require("game/ui/sequence/action/CureAction");
require("game/ui/sequence/action/DamageAction");
require("game/ui/sequence/action/DieAction");
require("game/ui/sequence/action/EscapeAction");
require("game/ui/sequence/action/HitAction");
require("game/ui/sequence/action/PrepareAction");
require("game/ui/sequence/action/StartAction");
require("game/ui/sequence/action/DodgeAction");
require("game/ui/sequence/action/ImmunityAction");
require("game/ui/sequence/action/DelayAction");
require("game/ui/sequence/action/BlockAction");
require("game/ui/sequence/action/InvincibleAction");
require("game/ui/sequence/action/RemoteAttackAction");
require("game/ui/sequence/action/ReflexAction");
require("game/ui/sequence/action/TransferAction");
require("game/ui/sequence/action/LinkAction");

-- 技能施展的播放序列
CastSequence = class("CastSequence");
function CastSequence.create(source, target, skillId)
    local self = CastSequence.new(source, target, skillId);
    self.source = source;
    self.target = target;
    self.skillId = skillId;
    return self;
end

--构造函数
function CastSequence:ctor(source, target, skillId)
    -- 技能施展的源和目标
    self.source = nil;
    self.target = nil;

    -- 使用那个技能进行攻击
    self.skillId = 0;

    -- 准备攻击的序列
    self.prepareStep = {};
    table.insert(self.prepareStep, PrepareAction.create(source, target));

    -- 攻击开始的序列
    self.startStep = {};

    -- 命中后的序列
    self.hitStep = {};

    -- 收尾序列
    self.endStep = {};
end

-- 判断是否有序列需要播放
function CastSequence:empty()
    local num = #self.prepareStep + #self.startStep + #self.hitStep + #self.endStep;
    return num == 0;
end

-- 播放序列, 每次只播放一个，并返回当前序列需要的时间
function CastSequence:play()
    self.lastDamageSkill = nil;

    for i = 1, #self.prepareStep do
        local action = self.prepareStep[i];
        table.removeItem(self.prepareStep, action);
        return action:play();
    end

    for i = 1, #self.startStep do
        local action = self.startStep[i];
        table.removeItem(self.startStep, action);
        return action:play();
    end

    for i = 1, #self.hitStep do
        local action = self.hitStep[i];
        table.removeItem(self.hitStep, action);
        return action:play();
    end

    for i = 1, #self.endStep do
        local action = self.endStep[i];
        table.removeItem(self.endStep, action);
        return action:play();
    end
end

-- 开始动作
function CastSequence:start(source, target, skillId)
    if #self.startStep > 0 then
        return;
    end

    table.insert(self.startStep, StartAction.create(source, target, skillId));
end

-- 远程怪攻击
function CastSequence:remoteAttack(source, target, skillId)
    -- 怪物受击动作
    table.insert(self.hitStep, RemoteAttackAction.create(source, target, skillId));
end

-- 命中
function CastSequence:hit(source, target, skillId)
    -- 怪物受击动作
    table.insert(self.hitStep, HitAction.create(source, target, skillId));
end

-- 闪避
function CastSequence:dodge(source, target)
    -- 怪物闪避动作
    table.insert(self.hitStep, DodgeAction.create(source, target));
end

-- 格挡（物理免疫）
function CastSequence:block(source, target)
    -- 怪物格挡动作
    table.insert(self.hitStep, BlockAction.create(source, target));
end

-- 免疫
function CastSequence:immunity(source, target)
    -- 怪物闪避动作
    table.insert(self.hitStep, ImmunityAction.create(source, target));
end

-- 无敌
function CastSequence:invincible(source, target)
    -- 怪物无敌动作
    table.insert(self.hitStep, InvicibleAction.create(source, target));
end

-- 反伤
function CastSequence:reflex(source, target)
    -- 怪物反击玩家
    table.insert(self.hitStep, ReflexAction.create(source, target));
end

-- 格挡（伤害转移）
function CastSequence:transfer(source, target, oriTarget)
    -- 伤害转移（原目标/转移目标）
    table.insert(self.hitStep, TransferAction.create(source, target, oriTarget));
end

-- 受到伤害
function CastSequence:receiveDamage(source, target, damage, skillId, extra)
    if damage == 0 then
        return;
    end

    local action = DamageAction.create(source, target, damage, skillId, extra);

    skillId = iif(skillId == nil, -1, skillId);

    self.lastDamageSkill = skillId;

    table.insert(self.hitStep, action);
end

-- 延迟动作
function CastSequence:delay(source, target, delay)
    table.insert(self.startStep, DelayAction.create(source, target, delay));
end

-- 延迟动作2（在hit阶段延迟）
function CastSequence:delay2(source, target, delay)
    printG("CastSequence:delay2")
    table.insert(self.hitStep, DelayAction.create(source, target, delay));
end

-- 受到治疗
function CastSequence:receiveCure(source, target, hp)
    if (target == self.source) then
        -- 可能是吸收伤害之类的，仍在最后面
        table.insert(self.endStep, CureAction.create(source, target, hp));
    else
        table.insert(self.hitStep, CureAction.create(source, target, hp));
    end
end

-- 死亡了
function CastSequence:die(source, target, damage, skillId)
    table.insert(self.endStep, DieAction.create(source, target, skillId));
end

-- 逃脱了
function CastSequence:escape(source)
    table.insert(self.endStep, EscapeAction.create(source));
end

-- 在两个格子之间播放特效
function CastSequence:link(source, target, skillId, linkCount)
    table.insert(self.hitStep, LinkAction.create(source, target, skillId, linkCount));
end

-- 转成CommonActionManager的格式
function CastSequence:getCommonActionCallbackList()
    local actionCallbackList = {}

    for i = 1, #self.prepareStep do
        local action = self.prepareStep[i];

        local function doAction()
            return action:play();
        end
        table.insert(actionCallbackList, doAction);
    end
    self.prepareStep = {};

    for i = 1, #self.startStep do
        local action = self.startStep[i];

        local function doAction()
            return action:play();
        end
        table.insert(actionCallbackList, doAction);
    end
    self.startStep = {};

    for i = 1, #self.hitStep do
        local action = self.hitStep[i];

        local function doAction()
            return action:play();
        end
        table.insert(actionCallbackList, doAction);
    end
    self.hitStep = {};

    for i = 1, #self.endStep do
        local action = self.endStep[i];

        local function doAction()
            return action:play();
        end
        table.insert(actionCallbackList, doAction);
    end
    self.endStep = {};

    return actionCallbackList;
end

return CastSequence;
